/*****************************************************************************
 * $LastChangedDate: 2011-09-25 12:03:59 -0400 (Sun, 25 Sep 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Sound sample (SDL_mixer music).
 * @remarks Samples don't know if sound is disabled (responsibility of Sound class).
 *          [2009/12] Implemented according to SDL_mixer 1.2.10 documentation.
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#if COMPILE_SDL_MIXER

#define SOUND_SOUND_SAMPLE_SDL_MUSIC_CC 1
#include "base/module.hh"
#include "base/stream.hh"
using namespace base;
#include "sound/module.hh"
#include "sound/defs.hh"
#include "sound/sound_sample.hh"
#include "sound/sound_sample_sdl_music.hh"

namespace sound {

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////  SampleSDLMusic  /////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * ctor
 * @param   sampleName
 * @param   mixMusic
 *          This object will then own mixMusic
 * Throws exception if error.
 *****************************************************************************/
SampleSDLMusic::SampleSDLMusic( const Sample::Name& sampleName, Mix_Music* mixMusic )
:   Sample(sampleName),
    mVolume(defs::DEFAULT_VOLUME),
    mMixMusic(mixMusic)
{
    // NOP
}

SampleSDLMusic::~SampleSDLMusic()
{
#if SOUND_FREE_SDL
    // void Mix_FreeMusic(Mix_Music *music)
    // music : Pointer to Mix_Music to free. 
    // Free the loaded music. If music is playing it will be halted.
    // If music is fading out, then this function will wait (blocking)
    // until the fade out is complete. 

    // Free SDL objects.
    if ( mMixMusic != NULL )
        Mix_FreeMusic( mMixMusic );

#endif // SOUND_FREE_SDL
}

/*****************************************************************************
 * @return True if sample is playing.
 *****************************************************************************/
bool
SampleSDLMusic::IfPlaying( void )
{
CHECK_TYPESIG(this,TYPESIG_SOUND_SAMPLE);

    return Mix_PlayingMusic();  // has no args
}

/*****************************************************************************
 * Play sound sample.
 * @param   playLoop
 *          Play continuously or once.
 * @param   volume
 *          Default is DEFAULT_VOLUME.
 * @return False if error.
 *****************************************************************************/
bool
SampleSDLMusic::Play( const defs::ePlayLoop playLoop, const fp volume )
{
CHECK_TYPESIG(this,TYPESIG_SOUND_SAMPLE);

    // int Mix_PlayMusic(Mix_Music *music, int loops)
    // music : Pointer to Mix_Music to play. 
    // loops : number of times to play through the music.
    //         0 plays the music zero times...
    //         -1 plays the music forever (or as close as it can get to that) 
    // Play the loaded music loop times through from start to finish.
    // The previous music will be halted, or if fading out it waits (blocking) for that to finish.
    // Returns: 0 on success, or -1 on errors.

    if ( Mix_PlayMusic( mMixMusic, (playLoop == defs::PLAY_LOOP) ? -1 : 1 ) == 0 )
    {
        // Now set volume.
        if ( SetVolume( volume ) )
        {
            return true;
        }
        else
        {
            #if LOG_SOUND_ERRORS
            CERROR << "ERROR[SampleSDLMusic::Play] Mix_PlayMusic() succeeded but SetVolume() failed " << GetName() << std::endl;
            PRINT_SDL_ERROR();
            #endif

            return false;
        }
    }
    else
    {
        #if LOG_SOUND_ERRORS
        CERROR << "ERROR[SampleSDLMusic::Play] Mix_PlayMusic() " << GetName() << std::endl;
        PRINT_SDL_ERROR();
        #endif

        return false;
    }
}

/*****************************************************************************
 * Stop playing a sound sample.
 * @return False if error.
 *****************************************************************************/
bool
SampleSDLMusic::Stop( void )
{
CHECK_TYPESIG(this,TYPESIG_SOUND_SAMPLE);

  //Mix_PauseMusic();
    Mix_HaltMusic();

    return true;
}

/*****************************************************************************
 * Set volume of a sound sample.
 * @return False if error.
 *****************************************************************************/
bool
SampleSDLMusic::SetVolume( const fp volume )
{
CHECK_TYPESIG(this,TYPESIG_SOUND_SAMPLE);

    // int Mix_VolumeMusic(int volume)
    // volume : Music volume, from 0 to MIX_MAX_VOLUME(128).
    //          Values greater than MIX_MAX_VOLUME will use MIX_MAX_VOLUME.
    //         -1 does not set the volume, but does return the current volume setting. 
    // Set the volume to volume, if it is 0 or greater, and return the previous volume setting.
    // Setting the volume during a fade will not work,
    // the faders use this function to perform their effect!
    // Setting volume while using an external music player set by Mix_SetMusicCMD
    // will have no effect, and Mix_GetError will show the reason why not.
    // Returns: The previous volume setting. 

    mVolume = volume;
    Mix_VolumeMusic( volume * MIX_MAX_VOLUME );

    return true;
}

/*****************************************************************************
 * @return Volume of a sound sample.
 *****************************************************************************/
fp
SampleSDLMusic::GetVolume( void )
{
CHECK_TYPESIG(this,TYPESIG_SOUND_SAMPLE);

    return mVolume;
}

} // namespace sound

#endif // COMPILE_SDL_MIXER
